#include "pthread_pool.h"

// 线程池初始化函数
P_SPI Pthread_Pool_Init()
{
    // 创建线程池的主结构体堆空间
    P_SPI p_spi = (P_SPI)malloc(sizeof(SPI));
    if (p_spi == (P_SPI)NULL)
    {
        perror("malloc ...");
        return (P_SPI)-1;
    }

    // 清空主结构体堆空间
    memset(p_spi, 0, sizeof(SPI));

    // 创建任务链表头节点
    if ((p_spi->task_head = Create_Task_Node()) == (Task_Link)-1)
    {
        printf("创建任务链表头节点失败！\n");
        free(p_spi);
        return (P_SPI)-1;
    }

    // 初始化条件变量
    if (pthread_cond_init(&p_spi->cond, NULL) != 0)
    {
        perror("pthread_cond_init ...");
        free(p_spi->task_head);
        free(p_spi);
        return (P_SPI)-1;
    }

    // 初始化互斥锁
    if (pthread_mutex_init(&p_spi->mute, NULL) != 0)
    {
        perror("pthread_mutex_init ...");
        pthread_cond_destroy(&p_spi->cond);
        free(p_spi->task_head);
        free(p_spi);
        return (P_SPI)-1;
    }

    // 创建监工线程
    if (pthread_create(&p_spi->monitor_pid, NULL, Monitor_Task, p_spi) != 0)
    {
        perror("pthread_create ...");
        Pthread_Pool_Free(p_spi);
        return (P_SPI)-1;
    }

    // 循环创建劳动线程
    for (int index = 0; index < PTHREAD_MAX_NUM; index++)
    {
        if (pthread_create(&p_spi->pid[index], NULL, Pthread_Pool_Manage, p_spi) != 0)
        {
            perror("pthraed_create ...");
            Pthread_Pool_Free(p_spi);
            return (P_SPI)-1;
        }

        pthread_mutex_lock(&p_spi->mute);   // 上锁
        p_spi->pthread_sum++;               // 线程总数+1
        p_spi->running_num++;               // 醒的线程数+1
        pthread_mutex_unlock(&p_spi->mute); // 解锁
    }

    return p_spi; // 返回堆空间基地址
}

// 创建任务链表头节点
Task_Link Create_Task_Node()
{
    Task_Link task = (Task_Link)malloc(sizeof(Task_Node));
    if (task == (Task_Link)NULL)
    {
        perror("malloc ...");
        return (Task_Link)-1;
    }

    memset(task, 0, sizeof(Task_Node));

    task->next = (Task_Link)NULL;

    return task;
}

// 监工线程任务函数
void *Monitor_Task(void *arg)
{
    P_SPI p_spi = (P_SPI)arg;
    pthread_detach(pthread_self()); // 线程设置自己为分离属性

    while (1)
    {
        sleep(10);
        pthread_mutex_lock(&p_spi->mute); // 上锁
        // printf("\n任务数：%u---线程总数：%u---工作中：%u---睡觉中：%u---醒的中：%u\n",
        //        p_spi->task_sum,
        //        p_spi->pthread_sum,
        //        p_spi->working_num,
        //        p_spi->sleepping_num,
        //        p_spi->running_num);

        pthread_mutex_unlock(&p_spi->mute); // 解锁
    }

    pthread_exit((void *)0);
}

// 劳动线程任务函数
void *Pthread_Pool_Manage(void *arg)
{
    P_SPI p_spi = (P_SPI)arg;

    while (!(p_spi->destory_mask))
    {
        // 上锁
        pthread_mutex_lock(&p_spi->mute);

        // 判断是否有任务
        if (p_spi->task_head->next == (Task_Link)NULL && p_spi->task_sum == 0)
        {
            // printf("我是%ld号线程，现在没任务，去睡觉！\n", pthread_self());
            p_spi->sleepping_num++; // 睡觉数+1
            p_spi->running_num--;
            pthread_cond_wait(&p_spi->cond, &p_spi->mute);
            p_spi->sleepping_num--; // 睡觉数-1
            p_spi->running_num++;   // 醒数+1
            // 解锁
            pthread_mutex_unlock(&p_spi->mute);
        }
        else // 有任务
        {
            // 去任务链表中取任务结点 --- 头删法
            Task_Link task = Get_Task(p_spi->task_head);
            if (task == (Task_Link)-1)
            {
                printf("获取任务结点失败！\n");
                pthread_exit((void *)-1);
            }

            p_spi->working_num++;               // 工作线程数+1
            p_spi->task_sum--;                  // 任务数-1
            pthread_mutex_unlock(&p_spi->mute); // 解锁

            // 回调函数进行执行任务
            task->Task(task);

            // 释放任务结点
            free(task);

            pthread_mutex_lock(&p_spi->mute);   // 上锁
            p_spi->working_num--;               // 工作线程数-1
            pthread_mutex_unlock(&p_spi->mute); // 解锁
        }
    }

    pthread_exit((void *)0);
}

// 从任务链表中获取一个任务结点
Task_Link Get_Task(Task_Link task_head)
{
    if (task_head == (Task_Link)NULL)
    {
        // printf("链表异常(取任务)！\n");
        return (Task_Link)-1;
    }

    Task_Link task = task_head->next;

    task_head->next = task->next;
    task->next = (Get_Task)NULL;

    return task;
}

// 创建任务结点
bool Add_Task_Node(P_SPI p_spi, char *task_refer, P_CN client_node)
{
    // 判断头结点是否异常
    if (p_spi->task_head == (Task_Link)NULL)
    {
        printf("任务链表异常(创建)！\n");
        return false;
    }

    // 创建任务结点，存放工作描述，
    Task_Link task_node = Create_Task_Node();
    if (task_node == (Task_Link)-1)
    {
        printf("创建任务结点失败！\n");
        return false;
    }

    strcpy(task_node->work_refer, task_refer); // 获取该工作的描述
    task_node->client_node = client_node;
    task_node->Task = Task;

    pthread_mutex_lock(&p_spi->mute); // 上锁

    // 进行尾插
    Task_Link end_node = p_spi->task_head;
    for (; end_node->next != (Task_Link)NULL; end_node = end_node->next)
        ;
    end_node->next = task_node;

    // 任务数量+1
    p_spi->task_sum++;

    pthread_mutex_unlock(&p_spi->mute); // 解锁

    return true;
}

// 任务处理函数
void *Task(void *arg)
{
    Task_Link task = (Task_Link)arg;

    // 根据任务类型执行不同的处理逻辑
    if (strcmp(task->work_refer, "客户端连接") == 0)
    {
        clinet_connect(task->client_node);
        return (void *)0;
    }
    else
    {
        // client_msg_handle(task->client_node, task->work_refer);
    }

    return (void *)0;
}

// 客户端连接处理
void clinet_connect(P_CN client_node)
{
    // 上锁
    pthread_mutex_lock(&client_node->server_inf_struct->mutex);

    // 尾插法添加客户端结点到在线客户链表中
    Add_Client_Node(client_node->server_inf_struct->online_client_head, client_node);

    // 解锁
    pthread_mutex_unlock(&client_node->server_inf_struct->mutex);

    // 创建线程接收当前客户端发送过来的消息
    if (pthread_create(&client_node->cli_pid, NULL, Mode_Select, client_node) != 0)
    {
        perror("pthread_create ...");
        pthread_exit((void *)-1);
    }
}

// 客户端消息处理
void client_msg_handle(P_CN client_node, char *msg)
{
    if (strstr(PRIVATE_CHAT, msg) == 0 && strlen(msg) > 10) // 私聊
    {
        printf("\n客户端：%s要私聊！\n", client_node->cli_ip);
        if (HandlePrivateChat(client_node->server_inf_struct, msg, client_node->cli_ip) == false)
        {
            // 如果没有找到目标客户端，发送错误消息
            char error_msg[256] = "PRIVATE_MSG:用户不在线或不存在";
            if (write(client_node->cli_fd, error_msg, strlen(error_msg)) == -1)
            {
                perror("write error message");
            }
        }
    }
    else if (strcmp(WE_CHAT, msg) == 0) // 群聊
    {
        printf("\n客户端：%s要群聊！\n", client_node->cli_ip);
        Broadcast_Task(client_node);
    }
    else if (strcmp(SHOW_WEATHER, msg) == 0) // 发送天气信息
    {
        char buffer[MSG_MAX_LEN];
        printf("\n客户端%s要显示天气\n", client_node->cli_ip);
        char *weather_info = get_weather();
        if (weather_info)
        {
            sprintf(buffer, "WEATHER:%s", weather_info);
            write(client_node->cli_fd, buffer, strlen(buffer));
            free(weather_info);
            printf("发送天气信息成功！\n");
        }
        else
        {
            printf("获取天气信息失败！\n");
        }
    }
    else if (strcmp(SHOW_ONLINE_CLI, msg) == 0) // 发送在线人员
    {
        printf("\n客户端%s要显示在线人员\n", client_node->cli_ip);
        Send_Onlie_Client(client_node->server_inf_struct, client_node);
    }
    else if (strcmp(TIME_MASK, msg) == 0) // 发送时间
    {
        char buffer[MSG_MAX_LEN];
        char *time_info = Get_Time();
        if (time_info)
        {
            sprintf(buffer, "TIME:%s", time_info);
            write(client_node->cli_fd, buffer, strlen(buffer));
            free(time_info);
        }
        else
        {
            printf("获取时间信息失败！\n");
        }
    }
    else if (strcmp(EXIT_MASK, msg) == 0) // 退出
    {
        return;
    }
    else // 网络传输有误
    {
        printf("Error...Error...Error! %s\n", msg);
    }
}

// 唤醒线程池中的所有线程
bool Wake_Up_Pthread(P_SPI p_spi)
{
    if (pthread_cond_broadcast(&p_spi->cond) != 0)
    {
        perror("pthread_cond_broadcast ...");
        return false;
    }

    return true;
}

// 摧毁线程池函数
bool Pthread_Pool_Free(P_SPI p_spi)
{
    if (p_spi->task_head == (Task_Link)NULL)
    {
        printf("链表异常(摧毁)！\n");
        return false;
    }
    // 把摧毁标志位设置1
    p_spi->destory_mask = 1;

    // 唤醒全部劳动线程
    pthread_cond_broadcast(&p_spi->cond);

    // 保证劳动线程都退出
    for (int index = 0; index < PTHREAD_MAX_NUM; index++)
    {
        if (pthread_join(p_spi->pid[index], NULL) != 0)
        {
            perror("pthread_join ...");
            return false;
        }
    }

    // 取消监工线程
    if (pthread_cancel(p_spi->monitor_pid) != 0)
    {
        perror("pthread_cancel ...");
        return false;
    }

    // 在摧毁 互斥锁 条件变量
    if (pthread_mutex_destroy(&p_spi->mute) != 0)
    {
        perror("pthread_mutex_destory ... ");
        return false;
    }

    if (pthread_cond_destroy(&p_spi->cond) != 0)
    {
        perror("pthread_mutex_destory ... ");
        return false;
    }

    // 摧毁任务链表
    while (p_spi->task_head->next != (Task_Link)NULL)
    {
        Task_Link free_node = p_spi->task_head->next;

        p_spi->task_head->next = free_node->next;

        free_node->next = (Task_Link)NULL;

        free(free_node);
    }

    free(p_spi->task_head);

    free(p_spi);

    return true;
}